package replica;

import generalResourceLalla.Task;
import generalResourceLalla.wsFormattedOperation.TaskEnvelope;
import generalResourceLalla.TaskList;
import java.io.*;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.concurrent.ArrayBlockingQueue;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import replica.stableMemory.StableFile;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author Ale
 */
public class ReplicaQueue {
    
    private long nodeId;
    private long replicaHostId;
    //private ArrayBlockingQueue<Task> queue;
    private TaskList list=new TaskList();
    public OutputStream w = null;
    public int capacity;
    public StableFile<TaskList> stableFile;
    

    
    public ReplicaQueue(long nodeId, long replicaHostId, int capacity)
    {
        this.nodeId=nodeId;
        this.replicaHostId=replicaHostId;
        //this.queue=new ArrayBlockingQueue(capacity);
        //File file = new File("files/ImageQueue/queue_"+this.replicaHostId+"_"+this.nodeId+".xml");
        this.capacity=capacity;
        this.stableFile=new StableFile<TaskList>("files/ImageQueue/queue_"+this.replicaHostId+"_"+this.nodeId+"/");
    }

    public TaskList getList() {
        return list;
    }
    
    
    
    public long getNodeId()
    {
        return this.nodeId;
    }

    public long getReplicaHostId() {
        return replicaHostId;
    }

    public void setReplicaHostId(long replicaHostId) {
        this.replicaHostId = replicaHostId;
    }

    public int getCapacity() {
        return capacity;
    }

    public long getSerial() {
        return this.list.getSerial();
    }
    
    public void setSerial(long serial) {
        this.list.setSerial(serial);
        this.stableFile.write(this.list); //ogni volta che viene settato un nuovo seriale bisogna aggiornare la lista salvata sul file
    }

    public void setList(TaskList list) {
        this.list = list;
    }
    
    
    
    public void enqueue(Task t)
    {
        try{
            this.getList().setSerial(this.list.getSerial()+1);
            //this.queue.add(t);
            this.list.add(t);
            this.stableFile.write(this.list);
            
        }
        catch(IllegalStateException ise)
        {
            System.err.println("ATTENZIONE: si sta cercando di inserire un task in una "
                + "coda replicata piena. Questo non e' possibile");
            ise.printStackTrace();System.exit(-8641);
        }

    }
    
    public void dequeue()
    {
        this.getList().setSerial(this.list.getSerial()+1);
        //Task task=this.queue.poll();
        Task task=this.list.remove(0);
        this.stableFile.write(this.list);
        
        //PER EBUG
        try{
            if(task==null)
                throw new NullPointerException("Attenzione: si sta provando a fare una"
                        + "dequeue su una coda replicata vuota. Questo non e' possibile");
        }catch(Exception e) 
        {
            e.printStackTrace();System.exit(-143);
        }
        //FINE PER DEBUG
    }
    
    public String toString()
    {
        String result=" ";
        for (Iterator it = list.iterator(); it.hasNext();) {
            Task t = (Task) it.next();
            result+=t.toString();
        }
        return result;
    }

    
    public void loadOnRebirth()
    {
        TaskList list=stableFile.read(TaskList.class);
        if (list!=null)
            this.list=list;
        else
            this.list= new TaskList();
        list= stableFile.read(TaskList.class);
    }

}
